package com.chaosj.tools

import java.util.concurrent.Phaser
import java.util.function.BiConsumer
import java.util.function.Predicate

/**
 * @Description:
 * @author: caoyangjie
 * @date: 2019年11月2019/11/26日 10:06
 * @Copyright: © 赢时胜
 */
class FileSearchFilter implements Runnable {
    private String initPath
    private Queue<String> results
    private Phaser phaser
    private Predicate<File> filter
    private BiConsumer<Queue<String>,File> collect

    FileSearchFilter(String initPath, Phaser phaser, Predicate<File> filter, BiConsumer<Queue<String>,File> collect) {
        this(initPath,phaser,filter,new LinkedList<>(),collect)
    }

    FileSearchFilter(String initPath, Phaser phaser, Predicate<File> filter, Queue<String> concurrentList, BiConsumer<Queue<String>,File> collect) {
        this.initPath = initPath
        this.phaser = phaser
        results = concurrentList
        this.filter = filter
        this.collect = collect
    }

    private void directoryProcess(File file) {
        File[] list = file.listFiles()
        if (list != null) {
            for (int i = 0; i < list.length; i++) {
                if (!list[i].isDirectory()) {
                    fileProcess(list[i],collect)
                } else {
                    directoryProcess(list[i])
                }
            }
        }
    }

    private void fileProcess(File file, BiConsumer<Queue<String>,File> collect) {
        if (filter.test(file)) {
            if( collect!=null ){
                collect.accept(results,file)
            }else{
                results.add(file.getName())
            }
        }
    }

    private boolean checkResults() {
        if (results.isEmpty()) {
            System.out.printf("%s: Phase %d: 0 results.\n", Thread
                    .currentThread().getName(), phaser.getPhase());
            System.out.printf("%s: Phase %d: End.\n", Thread.currentThread()
                    .getName(), phaser.getPhase())
            phaser.arriveAndDeregister()
            return false
        } else {
            System.out.printf("%s: Phase %d: %d results.\n", Thread
                    .currentThread().getName(), phaser.getPhase(), results
                    .size())
            phaser.arriveAndAwaitAdvance()
            return true
        }
    }

    @Override
    void run() {
        phaser.arriveAndAwaitAdvance()
        System.out.printf("%s: Starting.\n", Thread.currentThread().getName())
        File file = new File(initPath)
        if (file.isDirectory()) {
            directoryProcess(file)
        }
        if (!checkResults()) {
            return
        }
        phaser.arriveAndDeregister();
        System.out.printf("%s: Work completed.\n", Thread.currentThread()
                .getName())
    }

    Queue<String> getResults() {
        return results
    }
}
